// let isSMD: boolean = true // 定义一个布尔类型变量
// let age: number = 18 // 定义一个数字类型变量
// let myName: string = 'smd' // 定义字符串
// let arr1: number[] = [1, 2, 3] // 定义一个数字类型数组
// let arr2: Array<number> = [1, 2, 3] // 等价于上边
// // 元组类型 tuple  数量和类型已知的数组 -- 元组
// let xj: [string, number] = ['消金', 10]
// // 枚举类型 enum  定义一个变量，列举他可能出现的值
// enum Size { // 普通枚举
//   BIG,
//   SMALL
// }
// console.log(Size.BIG, Size[0]) // 0 BIG
// console.log(Size.SMALL, Size[1]) // 1 SMALL
// const enum Colors { // 常量枚举
//   RED,
//   YELLOW,
//   BLUE
// }
// const myColor = [Colors.RED, Colors.BLUE, Colors.YELLOW] // 编译后的结果为 var myColor = [0 /* RED */, 2 /* BLUE */, 1 /* YELLOW */];
// // 任意类型 any
// let root: any = document.getElementById('#root')
// // 如果一个变量定义成any类型 则它和js的使用时一样的
// root.style.color = 'red'
// // 如果 strictNullChecks的值为true 则不能这么用  因为null没有.style属性
// let element: (HTMLElement | null) = document.getElementById('#element')
// element!.style.color = 'blue'
// // null undefined 是其他类型的子类型(strictNullChecks不是true的情况下)
// let x: number = 1
// // x = undefined
// // x = null
// let y: number | null | undefined // 或操作符
// y = 1
// y = undefined
// y = null
// // 不会出现的值 never
// // 1.作为不会返回的函数的返回值类型
// function error(msg: string): never { // 返回值为never   不能里边什么都没有  如果什么都没有  他的返回值是undefined, undefined与never是不同的
//   throw Error('出错了')  // 出错了 下边的代码不会执行 也不会有返回值
//   console.log(msg)
// }
// error('123')
// function loop(msg: string): never { // while死循环  也不会有返回值
//   while (true) { }
//   console.log(msg)
// }
// function fn(x: number | string) {
//   if (typeof x === 'number') {
//     console.log(x.toFixed(0))
//   } else if (typeof x === 'string') {
//     console.log(x.trim())
//   } else {
//     console.log(x) // 这个x就是never类型的
//   }
// }
// // void 代表没有任何类型
// function voidFn(): void {
//   // return undefined // 可以返回undefined
//   // return null // 当strictNullChecks 为true时不能返回null   false时可以返回null
//   // return 123 // 其他的返回都不行
// }
// Symbol 唯一不变的类型
var s1 = Symbol('key');
var s2 = Symbol('key'); // “Symbol” 仅指类型，但在此处用作值。是否需要更改目标库? 请尝试将 “lib” 编译器选项更改为 es2015 或更高版本。
// 但是tsconfig设置了 lib之后  上边的console就不能用了  需要在lib中加上 “dom”
console.log(s1 === s2); // false
// BigInt
// let max = Number.MAX_SAFE_INTEGER  // 2**53-1 2的53次方-1  这是js中表示的最大的值
// console.log(max + 1 === max + 2) // true
var max = BigInt(Number.MAX_SAFE_INTEGER);
// 错误写法 console.log(max+1 === max+2) // 运算符“+”不能应用于类型“bigint”和“1”
// 正确写法 console.log(max + BigInt(1) === max + BigInt(2)) // false
// 简便写法 console.log(max + 1n === max + 2n) // 需要将tsconfig中的 target 改为 "ESNext"  数字后加个n表示大整形
var num;
var big;
// 错误写法 num = big  number与bigint类型的不能互转
// 类型推导
var uname; // 此时uname 会被ts推导为any类型
var uname2 = 'str'; // 声明变量并赋值 被类型推导为赋值的基本类型  等于uname2:string = 'str' 这种写法
// 错误 uname2 = 2  被类型推导后  不能再给他赋值为其他类型的变量
// 包装对象  wrapper object    
// 原始类型-对象类型
// 原始类型
var name2 = 'smd';
console.log(name2.toLocaleUpperCase()); // name2被推导为了字符串 但是字符串本身没有方法 在他的内部会进行自动包装对象：
console.log(new String(name2).toLocaleUpperCase());
// 联合类型
// 声明一个联合类型的变量name3 当它不赋值的时候，只能调用string和number共有的方法
var name3;
console.log(name3.toLocaleString(), name3.toString(), name3.valueOf());
// 但是当他赋值为具体类型之后，就可以调用当前类型下的方法了
name3 = 1;
console.log(name3.valueOf(), name3.toString(), name3.toPrecision(), name3.toLocaleString(), name3.toFixed(), name3.toExponential());
name3 = '1';
console.log(name3.sup(), name3.toLocaleLowerCase(), name3.toLocaleUpperCase(), name3.toLowerCase(), name3.toString(), name3.toUpperCase(), name3.trim(), '......');
// 类型断言
var name4;
// 错误写法 console.log(name4!.toFixed(2)); 直接掉length属性是会报错的 因为string上没有length属性
console.log(name4.toFixed(2)); // 将name4类型断言为name4
console.log(name4); // 双重断言 先断言成any  再断言成number
// 字面量类型与类型字面量
// 字面量类型
var up = 'Up';
var down = 'Down';
var left = 'Left';
var right = 'Right';
function move(direction) {
}
move('Down'); // 入参中只有 'Up' | 'Down' | 'Left' | 'Right' 这四个选项
var p1 = {
    name: 'smd',
    age: 18 // 缺一不可
};
var t1 = '1'; // 字面量联合类型规定只能是其中的某一个
var t2 = 1; // 值随意  只要类型满足其中一个就行
// 函数  可以指定函数的参数类型和返回值类型
function hello(name) {
    console.log("hello".concat(name));
}
hello('smd');
var myName = function (firstName, lastName) {
    return firstName + lastName;
};
// age 函数的可选参数
function print1(name, age) {
    console.log(name, age);
}
print1('smd', 18);
// methods 函数的可选参数
function ajax(url, methods) {
    if (methods === void 0) { methods = 'GET'; }
    console.log(url, methods);
}
ajax('/');
// numbers 剩余参数
function sum() {
    var numbers = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        numbers[_i] = arguments[_i];
    }
    return numbers.reduce(function (x, y) {
        return x + y;
    }, 0);
}
console.log(sum(1, 2, 3));
// 函数的重载
var obj = {};
function attr(val) {
    if (typeof val === 'string') {
        obj.name = val;
    }
    else if (typeof val === 'number') {
        obj.age = val;
    }
}
// 可以 attr('smd')
// 可以 attr(18)
// 不可以 attr(true) // 因为attr重载类型只规定了string和number
